package com.rookie.tool.module.util.thread.monitor;

import lombok.EqualsAndHashCode;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程监控器
 *
 * @author rookie
 */
public class ThreadMonitor {

    public static final ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor(16, 16,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(), new CustomizableThreadFactory("测试线程-" ));

    public static final Map<Thread, Map<String, Object>> THREAD_INFO = new HashMap<>();

    public static final Map<Thread, Future<?>> THREAD_HANDLE = new HashMap<>();

    public static void main(String[] args) {
        TestThread testThread = new TestThread();
        Future<?> submit = THREAD_POOL.submit(testThread);
        THREAD_HANDLE.put(testThread, submit);
        THREAD_POOL.shutdown();
    }

    public static void cancelTask(Future<?> task) {
        task.cancel(true);
    }

    public static Map<String, Object> getThreadInfo(Thread thread) {
        return THREAD_INFO.get(thread);
    }

    public static String getThreadRunInfo(Thread thread) {
        return Arrays.toString(thread.getStackTrace());
    }

    public static long getRuntime(Thread thread){
        Map<String, Object> stringObjectMap = THREAD_INFO.get(thread);
        if (stringObjectMap == null){
            return 0;
        }
        long time = (long)stringObjectMap.get("START_TIME");
        return System.currentTimeMillis() - time;
    }


    @EqualsAndHashCode(callSuper = false)
    static class TestThread extends RunTimeThead {

        @Override
        protected void coreProcess() {
            System.out.println(4535435);
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(777);
        }
    }


    abstract static class RunTimeThead extends Thread {

        /**
         * 核心运行内容
         */
        abstract protected void coreProcess();

        @Override
        public void run() {
            try {
                long startTime = System.currentTimeMillis();
                Map<String, Object> infoMap = ThreadMonitor.THREAD_INFO.get(this);
                if (infoMap == null) {
                    infoMap = new HashMap<>();
                }
                infoMap.put("START_TIME", startTime);
                this.coreProcess();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                ThreadMonitor.THREAD_INFO.remove(this);
            }
        }
    }
}
